1 /* 2 Copyright: Marcelo S. N. Mancini (Hipreme|MrcSnm), 2018 - 2021 3 License: [https://creativecommons.org/licenses/by/4.0/|CC BY-4.0 License]. 4 Authors: Marcelo S. N. Mancini 5 6 Copyright Marcelo S. N. Mancini 2018 - 2021. 7 Distributed under the CC BY-4.0 License. 8 (See accompanying file LICENSE.txt or copy at 9 https://creativecommons.org/licenses/by/4.0/ 10 */ 11 module hip.math.random; 12 import core.stdc.stdlib; 13 14 version(WebAssembly) extern(C) float JS_Math_random() @nogc nothrow; 15 version(PSVita) extern(C) int psv_rand() @nogc nothrow; 16 17 class Random 18 { 19 @disable this(); 20 21 // version(Android) 22 // { 23 // import std.random; 24 // private __gshared std.random.Random randomGenerator; 25 // } 26 static void initialize() 27 { 28 version(WebAssembly){} else 29 { 30 import core.stdc.time; 31 srand(cast(uint)time(null)); 32 } 33 // version(Android) 34 // { 35 // import std.random; 36 // randomGenerator = std.random.Random(std.random.unpredictableSeed()); 37 // } 38 } 39 40 @nogc nothrow 41 { 42 static float rangef(float min, float max) 43 { 44 version(WebAssembly){return JS_Math_random() * (max-min) + min;} 45 else version(PSVita){return (cast(float)psv_rand() / RAND_MAX) * (max-min) + min;} 46 //else version(Android){return std.random.uniform(cast(int)min, cast(int)max, randomGenerator);} 47 else 48 return (cast(float)rand() / RAND_MAX) * (max-min) + min; 49 } 50 static int range(int min, int max) 51 { 52 return cast(int)rangef(min, max); 53 } 54 static uint rangeu(uint min, uint max) 55 { 56 return cast(uint)rangef(min, max); 57 } 58 static ubyte rangeub(ubyte min, ubyte max) 59 { 60 return cast(ubyte)rangef(min, max); 61 } 62 } 63 64 /** 65 * This function gets a container and returns a random value from it. 66 * It may not receive any weight, so, it will be normally distributed (I expect) 67 * If it receives less weights than it has values, the last value will contain a weight equals 68 * to 1 - sum(weights) 69 * The weights must sum up to 1.0 70 */ 71 static T select(T)(in T[] container, float[] weights = []) @nogc nothrow 72 { 73 if(weights.length == 0) 74 { 75 int min = 0; 76 int max = cast(int)(container.length) - 1; 77 int index = range(min, max); 78 79 return container[index]; 80 } 81 82 float currentSum = 0; 83 float selectedValue = rangef(0.0, 1.0); 84 85 for(int i = 0; i < weights.length; i++) 86 { 87 if(selectedValue >= currentSum && selectedValue <= currentSum+weights[i]) 88 return container[i]; 89 currentSum+= weights[i]; 90 } 91 return container[$-1]; 92 } 93 94 }